#ifndef VEC2_HPP
#define VEC2_HPP

#include "math.h"

template <typename T>
class VEC2
{
public:
    // direct variable access
    T    x, y;
    
    // initialization
    VEC2 ( );
    VEC2 (T a);
    VEC2 (T a, T b);
    VEC2 (const VEC2 &v);
    
    // operators
    VEC2 operator = (const VEC2 &v);            // assignment
    VEC2 operator + (const VEC2 &v) const;        // addition, by element
    VEC2 operator - (const VEC2 &v) const;        // subtraction, by element
    T    operator * (const VEC2 &v) const;        // dot product
    VEC2 operator * (const T &s) const;            // multiplication by a scalar
    VEC2 operator / (const T &s) const;            // division by a scalar
    VEC2 operator - () const;                    // negation
    T&   operator[] (const int i);                // access of members
    bool operator ==(const VEC2<T> &v) const;         // equality test
    
    // named operation functions
    T dot(const VEC2 &v) const;
    // note: there is no cross product for 2d vectors
    T length() const;
    VEC2 normalized () const;
    void normalize();
    
};

// I REALLY REALLY hate doing this

// initialization
template  <typename T>
VEC2<T>::VEC2 ( )
{
    x = (T)0.0;
    y = (T)0.0;
}

template  <typename T>
VEC2<T>::VEC2 (T a)
{
    x = a;
    y = a;
}

template  <typename T>
VEC2<T>::VEC2 (T a, T b)
{
    x = a;
    y = b;
}

template  <typename T>
VEC2<T>::VEC2 (const VEC2<T> &v)
{
    x = v.x;
    y = v.y;
}

// operators
template  <typename T>
VEC2<T> VEC2<T>::operator = (const VEC2<T> &v)            // assignment
{
    x = v.x;
    y = v.y;
    return (*this) ;
}

template  <typename T>
VEC2<T> VEC2<T>::operator + (const VEC2<T> &v) const        // addition, by element
{
    return VEC2(x + v.x, y + v.y);
}

template  <typename T>
VEC2<T> VEC2<T>::operator - (const VEC2<T> &v) const        // subtraction, by element
{
    return VEC2(x - v.x, y - v.y);
}

template  <typename T>
T    VEC2<T>::operator * (const VEC2<T> &v) const        // dot product
{
    return x * v.x + y * v.y;
}

template  <typename T>
VEC2<T> VEC2<T>::operator * (const T &s) const    // multiplication by a scalar
{
    return VEC2(x * s, y * s);
}

template  <typename T>
VEC2<T> VEC2<T>::operator / (const T &s) const    // division by a scalar
{
    return VEC2(x / s, y / s);
}

template  <typename T>
VEC2<T> VEC2<T>::operator - () const            // negation
{
    return VEC2(-x, -y);
}

template  <typename T>
T& VEC2<T>::operator[] (const int i)        // access if of members
{
    if (i <= 0)
        return &x;
    if (i >= 1)
        return &y;
}

template  <typename T>
bool VEC2<T>::operator ==(const VEC2<T> &v) const         // equality test
{
    return (x == v.x && y == v.y);
}

// named operation functions

template  <typename T>
T VEC2<T>::dot(const VEC2<T> &v) const
{
    return x * v.x + y * v.y;
}

template <typename T>
T VEC2<T>::length() const
{
    return (T)sqrt((double)x*x + (double)y*y);
}

template  <typename T>
VEC2<T> VEC2<T>::normalized () const
{
    T len = this->length();
    if (len < 0.00001)
        return VEC2(0, 0);
    return VEC2(x / len, y / len);

}

template  <typename T>
void VEC2<T>::normalize()
{
    T len = this->length();
    if (len < 0.00001)
        return;
    x = x / len;
    y = y / len;
}

#endif